#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <time.h>

#define BUFLEN 8192 /* in bytes, 8KB */
#define TCP_PORT   6889
#define UDP_PORT	9983
#define RESPONSE_TCP_PORT   7689
#define RESPONSE_UDP_PORT   9783
#define SYN_PORT   6789


int msgCounter;//contatore di messaggi
int sleep_send;
int **aperiodic; //matrice [idSensore, numRichieste aperiodiche]
int **periodic;	//matrice [idSensore, numRichieste periodiche]
int aperRows;
int perRows;
struct tm* diff_time;
pthread_mutex_t M;  //server per il msgCounter
pthread_mutex_t M_sleep;  //server per l'accesso a sleep value
pthread_mutex_t file1;  //server per il file "send_traffic_periodic.txt"
pthread_mutex_t file2;  //server per il file "send_traffic_periodic.txt"
pthread_mutex_t mutex_diff_time;


 
void *single_request_periodic(void *arg);
void *obtain_responce_periodic();
void *thread_obtain_responce_periodic(void *arg);
void *request_aperiodic_sensor_value();
void *obtain_responce_aperiodic();
void delay(int t); //aspetta un tempo uguale a 100000 cicli macchina per t
void add_new_aperiodic_request();
void add_new_periodic_request();
void send_all_request();
void *syn();

int main() {

	msgCounter = 0;
	sleep_send=1000; //1 sec.
	aperiodic=NULL;
	periodic=NULL;
	aperRows=0;
	perRows=0;
	pthread_mutex_init(&M,NULL);
	pthread_mutex_init(&file1,NULL);
	pthread_mutex_init(&file2,NULL);
	pthread_mutex_init(&M_sleep,NULL);
	pthread_mutex_init(&mutex_diff_time,NULL);
	diff_time = malloc(sizeof(struct tm));
	
    int scelta;
    
    do
    {
        printf("\nRichiesta Aperiodica (1)");
        printf("\nRichiesta Periodica (2)");
        printf("\nInvio richieste (3)");
        printf("\nFai la tua scelta: ");
        scanf("%d",&scelta);
        
        switch(scelta)
        {
                      case 1:
                           add_new_aperiodic_request();
                           break;
                      case 2:
                      	   add_new_periodic_request();
                           break;
                      case 3:
                      	   send_all_request();
                           break;
                      default:
                           printf("\n\nErrore! Non hai fatto una scelta corretta tra quelle possibili! Riprova!\n ");
                           break;
                           
        }
    }while(scelta!=3);

	pthread_exit(0);
}



//Funzione che permette di aggiungere una richiesta periodica nella matrice 'periodic'
void add_new_aperiodic_request(){
	int idSensor,numPacket;
	printf("\n\nInserisci l'id del Sensore: ");
    scanf("%d",&idSensor);
    printf("Inserisci in numero di richieste da inviare: ");
    scanf("%d",&numPacket);
    
    if(aperiodic==NULL){
    	//se sono qui, sto inserendo il primo elemento nella matrice aperiodic
		aperiodic = (int**)malloc(sizeof(int(*)));
		*(aperiodic)=(int*)malloc(3*sizeof(int));
		aperiodic[0][0]=idSensor;
		aperiodic[0][1]=numPacket;
		aperiodic[0][2]=0;
		aperRows++;
	}else{
		//se sono qui, almeno un elemento nella matrice aperiodic c'è --> quindi REALLOC
		printf("Num righe:%d\n",aperRows);
		aperiodic = (int**)realloc(aperiodic,(aperRows+1)*sizeof(int*));
		aperiodic[aperRows]=(int*)malloc(3*sizeof(int));
		aperiodic[aperRows][0]=idSensor;
		aperiodic[aperRows][1]=numPacket;
		aperiodic[0][2]=0; //di default deadline NON scaduta
		aperRows++;
	}
	
	
	int i;
	for(i=0;i<(aperRows);i++){
		printf("\nidSensor: %d\tnumPacket: %d\n",aperiodic[i][0],aperiodic[i][1]);
	}
	
		
}

//Funzione che permette di aggiungere una richiesta periodica nella matrice 'periodic'
void add_new_periodic_request(){
	int idSensor,period;
	printf("\n\nInserisci l'id del Sensore: ");
	scanf("%d",&idSensor);
	printf("Inserisci il periodo richiesto: ");
	scanf("%d",&period);
    
	if(periodic==NULL){
    	//se sono qui, sto inserendo il primo elemento nella matrice aperiodic
		periodic = (int**)malloc(sizeof(int(*)));
		*(periodic)=(int*)malloc(2*sizeof(int));
		periodic[0][0]=idSensor;
		periodic[0][1]=period;
		perRows++;
	}else{
		//se sono qui, almeno un elemento nella matrice aperiodic c'è --> quindi REALLOC
		printf("Num righe:%d\n",perRows);
		periodic = (int**)realloc(periodic,(perRows+1)*sizeof(int*));
		periodic[perRows]=(int*)malloc(2*sizeof(int));
		periodic[perRows][0]=idSensor;
		periodic[perRows][1]=period;
		perRows++;
	}
	/*
	int i;
	for(i=0;i<(perRows);i++){
	printf("\nidSensor: %d\tperiod: %d\n",periodic[i][0],periodic[i][1]);
	}
	*/
}


/*FUNZIONE CHE Crea i thread in base alle richieste dell'utente --> cioè i thread che si occupano delle richieste periodiche e aperiodiche*/
void send_all_request(){
	pthread_t syn_thread;
	pthread_create(&syn_thread,NULL,syn,NULL);
	sleep(3);
	if(periodic!=NULL){
		FILE *f2;
		f2=fopen("send_traffic_periodic.txt", "w");
		fclose(f2);

		pthread_t responce_periodic_thread;
		
		pthread_create(&responce_periodic_thread,NULL,obtain_responce_periodic,NULL);
		sleep(3);
		printf("Num righe matrice periodica:%d\n",perRows);
		int l;//scorro tutte le richieste
		for(l=0;l<(perRows);l++){
			pthread_t thread_single_request_periodic;
			pthread_create(&thread_single_request_periodic,NULL,single_request_periodic,(void *)l);			
		}//fine for
	}
	if(aperiodic!=NULL){
		printf("Num righe matrice aperiodica:%d\n",aperRows);
		pthread_t request_aperiodic_thread,responce_aperiodic_thread;
		pthread_create(&responce_aperiodic_thread,NULL,obtain_responce_aperiodic,NULL);
		sleep(3);
		pthread_create(&request_aperiodic_thread,NULL,request_aperiodic_sensor_value,NULL);
	}

}



void *syn(){
	int sd;/* Il socket descriptor del client */
	int sleep_value;
	struct sockaddr_in server_addr; // l'indirizzo del server 

	// Utilizzando la struttura hostent si definisce l'indirizzo del server 
	struct hostent *hp;
	hp = gethostbyname("0.0.0.0");
	//hp = gethostbyname("192.168.1.1");

	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SYN_PORT);
	// successivamente viene memorizzato nella struttura server_addr 
	server_addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr;

	//Viene creato il socket descriptor
	if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		printf("Errore nella creazione della socket\n");

	printf("\n\nSincronizzazione: Numero Socket usato dalla wifi per MANDARE RICHIESTE alla soekris: %d\n",sd);

	// Viene connesso al server
	if(connect(sd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
		printf("Errore di connessione al server\n");
	
	while(1){
		printf("\n----------- START SYNCRO -------------\n");
		struct tm* firstTime; //tempo prima dell'invio di TIME
		time_t t1;	
		time(&t1);
		firstTime=localtime(&t1);
	
		write(sd,"TIME",strlen("TIME"));
	
		char buf[BUFLEN];
		int anno;
		int mese;
		int giorno;
		int ora;
		int minuti;
		int secondi;
		read(sd, buf, BUFLEN);
		sscanf(buf,"%d,%d,%d,%d,%d,%d", &anno,&mese,&giorno,&ora,&minuti,&secondi);

		struct tm* secondTime; //tempo dopo l'arrivo del pacchetto TIME
		time_t t2;	
		time(&t2);
		secondTime=localtime(&t2);
		
		printf("\nTime_wifi:%d %d %d %d %d %d\n",(secondTime->tm_year+1900),secondTime->tm_mon,secondTime->tm_mday,secondTime->tm_hour,secondTime->tm_min,secondTime->tm_sec);

		double confronto = difftime(t2,t1);
		//printf("\nConfronto tra date (in sec.): %.2lf\n",confronto);
		int rtt = (int) (confronto + 0.5);
		printf("\nRTT (in sec.): %d\n",rtt);

		struct tm* master_time = malloc(sizeof(struct tm));
		master_time->tm_year= ((anno)+1900);
		master_time->tm_mon= (mese);
		master_time->tm_mday= (giorno);
		master_time->tm_hour= (ora);
		master_time->tm_min= (minuti);
		master_time->tm_sec= (secondi);
		
		printf("\nTime_soekris:%d %d %d %d %d %d\n",((anno)+1900), mese, giorno, ora, minuti, secondi);
		
		pthread_mutex_lock(&mutex_diff_time);
		diff_time->tm_year=secondTime->tm_year - master_time->tm_year + 1900;
		diff_time->tm_mon=secondTime->tm_mon - master_time->tm_mon + 1;
		diff_time->tm_mday=secondTime->tm_mday - master_time->tm_mday;
		diff_time->tm_hour=secondTime->tm_hour - master_time->tm_hour;
		diff_time->tm_min=secondTime->tm_min - master_time->tm_min;
		diff_time->tm_sec=secondTime->tm_sec - master_time->tm_sec+ rtt/2;
		printf("\nDIFFERENZA TIME:%d,%d,%d,%d,%d,%d\n",diff_time->tm_year,diff_time->tm_mon,diff_time->tm_mday,diff_time->tm_hour,diff_time->tm_min,diff_time->tm_sec);
		pthread_mutex_unlock(&mutex_diff_time);
		
		printf("\n----------- END SYNCRO -------------\n");

		sleep(10);
	}	
	close(sd);
	
	pthread_exit(0);
}



//gestione richieste aperiodiche
void *request_aperiodic_sensor_value(){
	struct sockaddr_in si_other,si_me;
	int sd, i, slen=sizeof(si_other);
	int sleep_value=1000;
	FILE *f;
	f=fopen ("send_traffic_aperiodic.txt", "w");
	int h;
	for(h=0;h<(aperRows);h++){
		fprintf(f,"IDsensor: %d\tNumPacket: %d\n",aperiodic[h][0],aperiodic[h][1]);
	}
	fprintf(f,"\n\n");
 
	memset((char *) &si_other, 0, sizeof(si_other));
	si_other.sin_family = AF_INET;
	si_other.sin_port = htons(UDP_PORT);
	struct hostent *hp;
	//hp = gethostbyname("192.168.1.1");
	hp = gethostbyname("0.0.0.0");
	si_other.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr;
	
	//Viene creato il socket descriptor
	if ((sd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
		printf("Errore nella creazione della socket\n");
	
	memset((char *) &si_me, 0, sizeof(si_me));
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(UDP_PORT);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
		
	if (bind(sd, (struct sockaddr *) &si_me, sizeof(si_me))==-1)
		perror("Error in UDP bind\n");

	//copia del vettore aperiodic
	int numTotPacket = 0;
	int ap[aperRows][3];  // [idSensore, numPacketTOTALI per sensore, numPAcket da inviare ad ogni intervallo temporale]
	int h2=0;
	for(h2=0;h2<aperRows;h2++){
		ap[h2][0]=aperiodic[h2][0];
		ap[h2][1]=aperiodic[h2][1];
		numTotPacket = numTotPacket + ap[h2][1];
	}
	printf("\nnumTotPacket : %d\n",numTotPacket );
	
	while(numTotPacket!=0){
		int i=0;
		for(i=0;i<aperRows;i++){
			int numMessaggiPerSensore = 0;
			if(ap[i][1]>5){
				numMessaggiPerSensore = random() % ap[i][1];
				ap[i][1] = ap[i][1] - numMessaggiPerSensore;
			}else if(ap[i][1]!=0){
				//se il num. di pacchetti da inviare è minore di 5 --> li invio tutti quelli restanti
				numMessaggiPerSensore = ap[i][1];
				ap[i][1] = 0;
			}
			printf("\nPer il sensore %d invierò %d pacchetti\n",ap[i][0],numMessaggiPerSensore);
			ap[i][2] = numMessaggiPerSensore;
			numTotPacket = numTotPacket - numMessaggiPerSensore;
		}
		
		int j=0;
		for(j=0;j<aperRows;j++){
		
			int numMessaggiDaInviare = ap[j][2];
		
			printf("numMessaggiDaInviare %d\n",numMessaggiDaInviare);
	
			while(numMessaggiDaInviare!=0){

				struct tm* newtime1;
				time_t t1;	
				time(&t1);
				newtime1=localtime(&t1);

				printf("\nTime_wifi:%d %d %d %d %d %d\n",(newtime1->tm_year+1900),newtime1->tm_mon,newtime1->tm_mday,newtime1->tm_hour,newtime1->tm_min,newtime1->tm_sec);
				fprintf(f,"TIMESTAMP: %d,%d,%d,%d,%d,%d\n", (newtime1->tm_year+1900),(newtime1->tm_mon+1),newtime1->tm_mday,newtime1->tm_hour,newtime1->tm_min,newtime1->tm_sec);

				char buf[BUFLEN];

				//lock sulla variabile condivisa msgCounter
				pthread_mutex_lock(&M);
				int idPacket = msgCounter;
				msgCounter++;
				pthread_mutex_unlock(&M);

				int idSensore = aperiodic[j][0];

				pthread_mutex_lock(&mutex_diff_time);
				int anno_pacch = newtime1->tm_year - diff_time->tm_year;	
				int mese_pacch = newtime1->tm_mon - diff_time->tm_mon + 1;
				int giorno_pacch = newtime1->tm_mday - diff_time->tm_mday;
				int ora_pacch = newtime1->tm_hour - diff_time->tm_hour;
				int minuti_pacch = newtime1->tm_min - diff_time->tm_min;
				int secondi_pacch = newtime1->tm_sec - diff_time->tm_sec;
				pthread_mutex_unlock(&mutex_diff_time);

				int deadline = (rand() % 15 +1);
				printf("\nValore Deadline: %d\n",deadline);

				char packet[BUFLEN];

				sprintf(packet ,"%d,%d,%d,%d,%d,%d,%d,%d,%d", idPacket,idSensore, anno_pacch,mese_pacch,giorno_pacch, ora_pacch,minuti_pacch, secondi_pacch,deadline);

				if (sendto(sd, packet, BUFLEN, 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
					printf("\nError in sendto UDP TIMESTAMP\n");

				//printf("\nMessaggio inviato!");
				printf("\nPacket di richiesta aperiodica inviato: %s\n",packet);

				//salvo su file:
				fprintf(f,"PACKET: %d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", idPacket,idSensore, anno_pacch,mese_pacch,giorno_pacch, ora_pacch,minuti_pacch, secondi_pacch,deadline);
			
				struct timeval tv;
				fd_set rset;
				int n;
				FD_ZERO(&rset);
				FD_SET(sd,&rset);
				tv.tv_sec=deadline;
				tv.tv_usec=0;
	
				n=select(sd+1,&rset,NULL,NULL,&tv);
				if(n==0){

					printf("\nE' scaduto il TIMEOUT di %d secondi\n",deadline);
					aperiodic[j][2] = 1; //setto deadline scaduta
					fprintf(f,"RESPONCE [PACKET]: EXPIRED\n\n");
					
				}else if(n<0){
					printf("\nErrore nella select\n");
				}else{
			
					if (recvfrom(sd, buf, BUFLEN , 0, (struct sockaddr *) &si_other, &slen)==-1)
						printf("\nError in UDP recvfrom()\n");
						
					fprintf(f,"RESPONCE: %s\n\n",buf);
		
					pthread_mutex_lock(&M_sleep);
					if(strcmp(buf,"SPEED_INCREASES")==0){
						//devo incrementare sleep_value;
						sleep_send = sleep_send + 1000;
						printf("\n\nSPEED_INCREASES!\n\n");
					}else if(strcmp(buf,"SPEED_DECREASE")==0){
						//devo decrementare sleep_value --> ma non devo andare al di sotto del valore "1000" (1 sec.)
						if(sleep_send!=1000){
							sleep_send = sleep_send - 1000;
							printf("\n\nSPEED_DECREASE! --> con DIMINUIZIONE\n\n");
						}else{
							printf("\n\nSPEED_DECREASE! --> SENZA DIMINUIZIONE [ho già raggiunto valore minimo]\n\n");
						}
					}else if(strcmp(buf,"ACK")==0){
						//Non faccio nulla
						printf("\n\nACK!\n\n");
					}
					sleep_value = sleep_send+(random()%3);
					pthread_mutex_unlock(&M_sleep);	
			
				}//else della SELECT
				delay(sleep_value);
				numMessaggiDaInviare--;

			}//fine while dei numMessaggiDaInviare per lo stesso idSensore
		 	
	 	}//fine ciclo for dei aperRows
	 	
	 	//aspetto un numero random minore di 10 prima di inviare il successivo set di pacchetti
	 	int attesa = random()%15 ;
	 	printf("\n\n ++++++ ATTENDO PER %d sec. ++++++\n\n",attesa);
	 	fprintf(f,"\nTempo di attesa prima di inviare nuovo set di pacchetti: %d\n\n\n",attesa); 
	 	sleep(attesa);
		
	}
 	
	close(sd);
	fclose(f);
	
	printf("\n\n ++++++ FINE PACCHETTI APERIODICI ++++++\n\n");
	
	pthread_exit(0);
}



/*
Thread che gestisce la singola richiesta periodica.
*/
void *single_request_periodic(void *arg){
	int sd;/* Il socket descriptor del client */
	int sleep_value;
	int j=(int) (arg);

	int periodo = periodic[j][1];
	FILE *f;
	//printf("creato 1 thread x gestire 1 req periodica");
	struct sockaddr_in server_addr; // l'indirizzo del server 

	// Utilizzando la struttura hostent si definisce l'indirizzo del server 
	struct hostent *hp;
	hp = gethostbyname("0.0.0.0");
	//hp = gethostbyname("192.168.1.1");

	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(TCP_PORT);
	// successivamente viene memorizzato nella struttura server_addr 
	server_addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr;

	//Viene creato il socket descriptor
	if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		printf("Errore nella creazione della socket\n");

	printf("\n\nPeriodic: Numero Socket usato dalla wifi per MANDARE RICHIESTE alla soekris: %d\n",sd);

	// Viene connesso al server
	if(connect(sd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
		printf("Errore di connessione al server\n");
	//pthread_mutex_lock(&mutex_thread1);
	char buf[BUFLEN];

	printf("sono il thread che gestisce la richiesta periodica %d di periodo %d\n\n", j, periodo);
	while(1){
		//lock sulla variabile condivisa msgCounter
		pthread_mutex_lock(&M);
		int idPacket = msgCounter;
		msgCounter++;
		pthread_mutex_unlock(&M);
	
		printf("richiesta periodica %d, pacchetto di id %d\n", j, idPacket);
		int idSensore = periodic[j][0];

		printf("\n\nSocket Number usato per inviare i dati: %d\n",sd);
	
		struct tm* newtime;
		time_t t;	
		time(&t);
		newtime=localtime(&t);
		//printf("anno_pacch: %d, mese:%d, giorno:%d.. %d %d %d",anno_pacch,mese_pacch,giorno_pacch,ora_pacch,minuti_pacch,secondi_pacch);
	
		//printf("1");
		pthread_mutex_lock(&mutex_diff_time);
		int anno_pacch = newtime->tm_year - diff_time->tm_year;	
		int mese_pacch = newtime->tm_mon - diff_time->tm_mon + 1;
		int giorno_pacch = newtime->tm_mday - diff_time->tm_mday;
		int ora_pacch = newtime->tm_hour - diff_time->tm_hour;
		int minuti_pacch = newtime->tm_min - diff_time->tm_min;
		int secondi_pacch = newtime->tm_sec - diff_time->tm_sec;
		pthread_mutex_unlock(&mutex_diff_time);

		//printf("anno_pacch: %d, mese:%d, giorno:%d.. %d %d %d",(anno_pacch+ 1900),mese_pacch,giorno_pacch,ora_pacch,minuti_pacch,secondi_pacch);
		int deadline=rand() % 10;
		//printf("2");

		//invio il pacchetto:
		//pthread_mutex_lock(&mutex_thread2);

		//invio il pacchetto:	
		char packet[BUFLEN];
	
		sprintf(packet ,"%d,%d,%d,%d,%d,%d,%d,%d,%d", idPacket,idSensore, anno_pacch,mese_pacch,giorno_pacch, ora_pacch,minuti_pacch, secondi_pacch,deadline);
		//printf("\nInvio packet: %s\n",packet);
		send(sd,packet,BUFLEN,0);
		printf("\nInviato pacchetto relativo a traffico periodico!");
		printf("\nNumero pacchetto: %d",idPacket);
		printf("\nID sensore : %d",idSensore);	
		printf("\nAnno: %d", anno_pacch);
		printf("\nMese: %d", mese_pacch);
		printf("\nGiorno: %d", giorno_pacch);
		printf("\nOra: %d", ora_pacch);
		printf("\nMinuti: %d", minuti_pacch);
		printf("\nSecondi: %d", secondi_pacch);
		printf("\nDeadline: %d", deadline);
		printf("\n#------- FINE -------#\n\n");
		printf("\n******************Messaggio %d, relativo a traffico periodico inviato!******************", idPacket);
	
		//ricevo il messaggi di risposta per regolare la velocità di invio dei pacchetti
		char responce_from_soekris[BUFLEN];
		read(sd, responce_from_soekris, BUFLEN);
		//pthread_mutex_unlock(&mutex_thread2);

		printf("\nRisposta dal server per regolare lo sleep: %s\n\n",responce_from_soekris);
		//salvo su file:
		pthread_mutex_lock(&file2);
		f=fopen ("send_traffic_periodic.txt", "a");
		fprintf(f,"\nTIMESTAMP: %d, %d, %d, %d, %d, %d\n",newtime->tm_year,newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);	
		fprintf(f,"PACKET: %d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", idPacket,idSensore, anno_pacch,mese_pacch,giorno_pacch, ora_pacch,minuti_pacch, secondi_pacch,deadline);	
		fprintf(f,"RESPONCE: %s\n\n",responce_from_soekris);
		fclose(f);
		pthread_mutex_unlock(&file2);

		pthread_mutex_lock(&M_sleep);
		if(strcmp(responce_from_soekris,"SPEED_INCREASES")==0){
			//devo incrementare sleep_value;
			sleep_send = sleep_send + 1000;
			printf("\n\nSPEED_INCREASES!\n\n");
		}else if(strcmp(responce_from_soekris,"SPEED_DECREASE")==0){
			//devo decrementare sleep_value --> ma non devo andare al di sotto del valore "1000" (1 sec.)
			if(sleep_send!=1000){
				sleep_send = sleep_send - 1000;
				printf("\n\nSPEED_DECREASE! --> con DIMINUIZIONE\n\n");
			}else{
				printf("\n\nSPEED_DECREASE! --> SENZA DIMINUIZIONE [ho già raggiunto valore minimo]\n\n");
			}
		}else if(strcmp(responce_from_soekris,"ACK")==0){
			//Non faccio nulla
			printf("\n\nACK!\n\n");
		}
		sleep_value = sleep_send;
		pthread_mutex_unlock(&M_sleep);

		delay(sleep_value);
		sleep(periodo);
	}//fine while

	
	//close(sd);

	//pthread_exit(0);

}


/*
Thread che sta in ascolto sulla porta "RESPONSE_PORT" e che si limita a sganciare un worker thread in caso di "accept" della connessione.
*/
void *obtain_responce_periodic(){

	FILE *f2;
	f2=fopen("received_traffic_periodic.txt", "w");
	fclose(f2);

	int sockfd, newsockfd, clilen;
	struct sockaddr_in cli_addr, serv_addr;
	pthread_t thread_listener_request;
	
	printf("Creazione Listener di RESPONCE\n");

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		printf("server: can't open stream socket\n");

	memset((char *) &serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(RESPONSE_TCP_PORT);

	
	if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
		printf("server: can't bind local address\n");	
	
	listen(sockfd, 200);
	
	printf("Listener di RESPONCE Creato e Socket creata\n");

	printf("Socket NUMBER del thread della wifi che si mette in ascolto delle risposte: %d",sockfd);

	for(;;){
		clilen = sizeof(cli_addr);
		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

		if(newsockfd < 0)
			printf("Listener di RESPONCE: accept error\n");

		/* create a new thread to process the incomming request */
		pthread_create(&thread_listener_request,NULL,thread_obtain_responce_periodic,(void *) newsockfd);

		/* the server is now free to accept another socket request */
	}
	close(sockfd);
}

/*
Worker Thread. Ha il compito di ricevere i messaggi di risposta contenenti i valori dei sensori e inviati dalla soekris.
Come sapete, purtroppo, ad ogni risposta verrà sganciato uno di questi thread. Il motivo di questa mi scelta è evitare che la wifi lavori alla stessa velocità del bluetooth.
I messaggi che riceve sono:
- numMsg
- idSensore
- sensorValue
*/
void *thread_obtain_responce_periodic(void *arg){
	int mysocfd = (int) arg;
	
	//pthread_mutex_lock(&mutex_thread3);

	char buf[BUFLEN];
	read(mysocfd, buf, BUFLEN);
	int numMsg;
	int idSensore;
	char dataValueSensore[BUFLEN];
	printf("\ndato ricevuto dalla soekris: %s\n", buf);
	sscanf(buf,"%d,%d,%s", &numMsg,&idSensore,dataValueSensore);

	//pthread_mutex_unlock(&mutex_thread3);
	
	//printf("\n1: %d , 2: %d , 3: %s\n",numMsg,idSensore,dataValueSensore);
	pthread_mutex_lock(&file1);
	FILE *f;
	f=fopen("received_traffic_periodic.txt", "a");
	fprintf(f,"IDmsg: %d\n",numMsg);
	fprintf(f,"IDSensore: %d\n",idSensore);
	fprintf(f,"SensorValue: %s\n\n",dataValueSensore);
 	pthread_mutex_unlock(&file1);
	fclose(f);
	if(strcmp(dataValueSensore,"EXPIRED")!=0){
	 	int sensorValue = atoi(dataValueSensore);
	 	printf("\nsensorValue: %d\n\n", sensorValue);
	}else{
		printf("\nERRORE! LA DEADLINE È SCADUTA! :( \n\n");
	}
	
	printf("\n --> Ho ricevuto: [%d,%d,%s] <--\n",numMsg,idSensore,dataValueSensore);
	
	//close(mysocfd);
	//pthread_exit((void *)0);
}//fine request_handling



void *obtain_responce_aperiodic(){

	FILE *f2;
	f2=fopen("received_traffic_aperiodic.txt", "w");
	fclose(f2);

	struct sockaddr_in si_me, si_other;
	int s, i, slen=sizeof(si_other);
	char buf[BUFLEN];

	if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
		printf("\nsocket\n");

	memset((char *) &si_me, 0, sizeof(si_me));
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(RESPONSE_UDP_PORT);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me))==-1)
		printf("\nError in bind\n");

	while(1){

		if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)==-1)
			printf("error in recvfrom()");	
	 	printf("\n\nNuovo MSG di risposta ricevuto --> [%s] <--\n",buf);

	 	int idMSG;
		int idSensor;
		int valu;
		char valueSensoreChar[BUFLEN];

		sscanf(buf,"%d,%d,%s", &idMSG,&idSensor,valueSensoreChar);

		if(strcmp(valueSensoreChar,"EXPIRED")==0){
			printf("\nidMsg: %d\n", idMSG);
			printf("idSensor: %d\n", idSensor);
			printf("ERRORE! LA DEADLINE È SCADUTA! :( \n\n");
		}else{
			int valu = atoi(valueSensoreChar);
			printf("\nidMsg: %d\n", idMSG);
			printf("idSensor: %d\n", idSensor);
		 	printf("sensorValue: %d\n\n", valu);
		}

		
		//salvataggio su file
		FILE *f;
		f=fopen("received_traffic_aperiodic.txt", "a");
		fprintf(f,"IDmsg: %d\tIDsensore: %d\tValore Sensore: %s\n",idMSG,idSensor,valueSensoreChar);
		struct tm* newtime1;
		time_t t1;	
		time(&t1);
		newtime1=localtime(&t1);
		printf("\nTime_wifi:%d %d %d %d %d %d\n",(newtime1->tm_year+1900),(newtime1->tm_mon+1),newtime1->tm_mday,newtime1->tm_hour,newtime1->tm_min,newtime1->tm_sec);
		fprintf(f,"TIMESTAMP WIFI [RECEIVED]: %d,%d,%d,%d,%d,%d\n\n", (newtime1->tm_year+1900),(newtime1->tm_mon+1),newtime1->tm_mday,newtime1->tm_hour,newtime1->tm_min,newtime1->tm_sec);
		fclose(f);
		
		//aggiorno il vettore "aperiodic"
		int i;
		for(i=0;i<(aperRows);i++){
			if(aperiodic[i][0]==idSensor){
				if(strcmp(valueSensoreChar,"EXPIRED")!=0){
				 	aperiodic[i][2] = 1;
				}else{
					aperiodic[i][2] = 0;
				}
			}
		}
		
		
	}//fine while(1)

}


/*
Poichè la funzione sleep accetta solo numeri interi per attendere Secondi e la funzione "usleep" non mi funzionava... mi sono inventata questa funzione
che consete di aspettare anche millisecondi!
*/
void delay(int t){
int i;
while(t>0){
	    for (i=0;i<100000;i++);
	    	t--;
	    }
}
